package org.inspursc.s0517.health.common.util;

import org.inspursc.s0517.health.common.entity.SysUser;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;

/**
 * Created by yuchuanfu on 2015/12/29.
 */
public class SpringSecurityUtils {

    /**
     * 取得当前用户, 返回值为UserInfo类或其子类, 如果当前用户未登录则返回null.
     */
    @SuppressWarnings("unchecked")
    public static <T extends SysUser> T getCurrentUser(HttpServletRequest request) {
        Authentication authentication = getAuthentication(request);
        if (authentication == null) {
            return null;
        }
        Object principal = authentication.getPrincipal();
        if (!(principal instanceof SysUser)) {
            return null;
        }
        return (T) principal;
    }

    /**
     * 取得当前用户的登录名, 如果当前用户未登录则返回空字符串.
     */
    public static String getCurrentUserName(HttpServletRequest request) {
        Authentication authentication = getAuthentication(request);

        if (authentication == null || authentication.getPrincipal() == null) {
            return "";
        }
        return authentication.getName();
    }



    /**
     * 取得当前用户的真实姓名, 如果当前用户未登录则返回空字符串.
     */
    public static String getCurrentName(HttpServletRequest request) {
        return getCurrentUser(request).getUsername();
    }

    /**
     * 取得当前用户登录IP, 如果当前用户未登录则返回空字符串.
     */
    public static String getCurrentUserIp(HttpServletRequest request) {
        Authentication authentication = getAuthentication(request);

        if (authentication == null) {
            return "";
        }

        Object details = authentication.getDetails();
        if (!(details instanceof WebAuthenticationDetails)) {
            return "";
        }
        WebAuthenticationDetails webDetails = (WebAuthenticationDetails) details;
        return webDetails.getRemoteAddress();
    }

    /**
     * 判断用户是否拥有角色, 如果用户拥有参数中的任意一个角色则返回true.
     */
    public static boolean hasAnyRole(String[] roles,HttpServletRequest request) {
        Authentication authentication = getAuthentication(request);

        if (authentication == null) {
            return false;
        }

        Collection<GrantedAuthority> grantedAuthorityList = (Collection<GrantedAuthority>) authentication.getAuthorities();
        for (String role : roles) {
            for (GrantedAuthority authority : grantedAuthorityList) {
                if (role.equals(authority.getAuthority())) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * 将UserDetails保存到Security Context.
     *
     * @param userDetails
     *            已初始化好的用户信息.
     * @param request
     *            用于获取用户IP地址信息,可为Null.
     */
    public static void saveUserDetailsToContext(UserDetails userDetails,
                                                HttpServletRequest request) {
        PreAuthenticatedAuthenticationToken authentication =
                new PreAuthenticatedAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities());
        if (request != null) {
            authentication.setDetails(new WebAuthenticationDetails(request));
        }
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }

    /**
     * 取得Authentication, 如当前SecurityContext为空时返回null.
     */
    public static Authentication getAuthentication(HttpServletRequest request) {

        SecurityContext context = SecurityContextHolder.getContext();

        if (context.getAuthentication() != null) {
            return context.getAuthentication();
        }else{
            SecurityContextImpl securityContextImpl = (SecurityContextImpl) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
            if(securityContextImpl!=null){
                return securityContextImpl.getAuthentication();
            }else {
                return null;
            }
        }
    }

}
